package com.zhiqian.community.service;

import com.zhiqian.community.dao.elasticsearch.DiscussPostRepository;
import com.zhiqian.community.entity.DiscussPost;
import com.zhiqian.community.entity.Page;
import com.zhiqian.community.util.CommunityConstant;
import com.zhiqian.community.util.MarkdownUtil;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

@Service
public class ElasticsearchService implements CommunityConstant{
    //预编译正则表达式
    private static final Pattern pattern1=Pattern.compile("\\&[a-zA-Z]{1,10};");
    private static final Pattern pattern2=Pattern.compile("<[^>]*>");
    private static final Pattern pattern3=Pattern.compile("[(/>)<]");
    @Autowired
    private DiscussPostRepository discussPostRepository;
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    @Autowired
    private DiscussPostService discussPostService;
    @Autowired
    private UserService userService;
    @Autowired
    private LikeService likeService;

    public void insertDiscussPost(Integer postId) {
        DiscussPost post = discussPostService.selectDiscussPostById(postId);
        //将markdown文本处理成普通文本
        post.setContent(MarkdownUtil.markdownToHtmlExtensions(post.getContent()).replaceAll(pattern1.pattern(), "").replaceAll(
                pattern2.pattern(), "").replaceAll(pattern3.pattern(), ""));
        discussPostRepository.save(post);
    }

    public void deleteDiscussPostById(Integer postId) {
        discussPostRepository.deleteById(postId);
    }

    public boolean existsDiscussPostById(Integer postId){
        return discussPostRepository.existsById(postId);
    }

    /**
     * 高亮搜索
     *
     * @param keyword
     * @param page
     * @return
     */
    public List<Map<String, Object>> search(String keyword, Page page) {
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "content"))
                .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
                .withSort(new ScoreSortBuilder())//按匹配度排序，默认倒序
                .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
                .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
                .withPageable(PageRequest.of(page.getCurrent()-1, page.getLimit()))
                .withHighlightFields(
                        new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),
                        new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")
                ).build();
        SearchHits<DiscussPost> searchHits = elasticsearchRestTemplate.search(searchQuery, DiscussPost.class);
        page.setRows((int) searchHits.getTotalHits());
        List<SearchHit<DiscussPost>> hitList = searchHits.getSearchHits();
        List<DiscussPost> discussPosts = new ArrayList<>();
        hitList.forEach(searchHit -> {
            Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
            searchHit.getContent().setTitle(highlightFields.get("title") == null ? searchHit.getContent().getTitle() : highlightFields.get("title").get(0));
            searchHit.getContent().setContent(highlightFields.get("content") == null ? searchHit.getContent().getContent() : highlightFields.get("content").get(0));
            discussPosts.add(searchHit.getContent());
        });
        return infoReplenish(discussPosts);
    }

    /**
     * 信息补充
     *
     * @param list
     * @return
     */
    private List<Map<String, Object>> infoReplenish(List<DiscussPost> list) {
        List<Map<String, Object>> result = new ArrayList();
        if (!list.isEmpty()) {
            list.forEach(discussPost -> {
                Map<String, Object> map = new HashMap<>(3);
                map.put("user", userService.getUserById(discussPost.getUserId()));
                map.put("post", discussPost);
                map.put("likeCount",likeService.queryEntityLikeCount(ENTITY_TYPE_POST,discussPost.getId()));
                result.add(map);
            });
        }
        return result;
    }

}
